#ifndef BASE_ARGS_SOLVE_HPP
#define BASE_ARGS_SOLVE_HPP

#include <functional>
#include <cxxabi.h>
#include <tuple>
#include <type_traits>
#include <iostream>

namespace reflect {

template<typename T>
struct function_traits;

// 处理普通函数
template<typename RET, typename ...ARGS>
struct function_traits<RET(ARGS...)>
{
    constexpr static size_t arity = sizeof...(ARGS);

    using function_type = RET(ARGS...);
    using Ret_type = RET;

    using stl_functional_type = std::function<function_type>;
    using function_pointer = RET(*)(ARGS...);

    template<size_t I>
    struct ArgN
    {
        static_assert(I < arity, "failed!");
        using type = std::tuple_element_t<I, std::tuple<ARGS...>>;
    };
    template<size_t I>
    using ArgN_t = typename ArgN<I>::type;
};

// 处理函数指针
template<typename RET, typename ...ARGS>
struct function_traits<RET(*)(ARGS...)> : function_traits<RET(ARGS...)> 
{
    using function_type = RET(*)(ARGS...);
};

// 处理std::function
template<typename RET, typename ...ARGS>
struct function_traits<std::function<RET(ARGS...)>> : function_traits<RET(ARGS...)>
{
    using function_type = std::function<RET(ARGS...)>;
};

//可变参数宏... <----> __VA_ARGS__ 对应替换

//处理成员函数
#define FUNCTION_TRAITS(...)                                                                                \
template<typename RET, typename Class, typename ...ARGS>                                                    \
struct function_traits<RET(Class::*)(ARGS...)__VA_ARGS__> : function_traits<RET(ARGS...)>                   \
{                                                                                                           \
    using function_type = RET(Class::*)(ARGS...);                                                           \
protected:                                                                                                  \
    using logic_function_type = RET(ARGS...);                                                               \
};                                                                                                          

FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)

//处理函数对象
template<typename Callable>
struct function_traits :function_traits<decltype(&Callable::operator())> 
{
	using function_type = typename function_traits<Callable>::logic_function_type;//函数对象模拟成普通函数的类型
};

template <typename T>
std::string Print_Type()
{
    int status;
    char* real_name;
    real_name = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
    std::string s(real_name);
    free(real_name);
    real_name = nullptr;
    return s;
}

template <typename T>
T Convert_Type(const std::string& str);

template <>
int Convert_Type<int>(const std::string& str)
{
    return std::stoi(str);
}

template<>
double Convert_Type<double>(const std::string& str)
{
    return std::stod(str);
}

template<>
std::string Convert_Type<std::string>(const std::string& str)
{
    return str;
}

}
#endif